﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime.CompilerServices;
namespace FileMonitor.Service.Provider.FileMonitor.TimerTrriger
{
    public enum ExcuteMode
    {
        Serial,
        Parallel
    }


    public class Trriger
    {
        private static ExcuteMode _excuteMode = ExcuteMode.Serial;
        private static TimeSpan _dueTime;
        private static TimeSpan _priod;
        private static object lockObj = new object();
        private static List<ITriggerProcess> RegisteredProcesses;
        private static int IsExcutingProcess=0;
        private static string currentFolder = AppDomain.CurrentDomain.BaseDirectory;
        private static string logPtah = string.Format("{0}{1}", currentFolder, "Log");
        // private static Timer TriggerTimer;
        private static System.Timers.Timer TriggerTimer;

        public static ExcuteMode ExcuteMode
        {
            get
            {
                return _excuteMode;
            }
            set
            {
                _excuteMode = value;
            }
        }

        public static TimeSpan DueTime
        {
            get { return _dueTime; }
        }

        public static TimeSpan Priod
        {
            get { return _priod; }
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public static void RegisterTriggerProcess(ITriggerProcess process)
        {
            Trriger.RegisteredProcesses.Add(process);
        }
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static void UnRegisterTriggerProcess(ITriggerProcess process)
        {
           Trriger.RegisteredProcesses.Remove(process);
        }

        public static void InitializeTrigger()
        {
            RegisteredProcesses = new List<ITriggerProcess>();
            double Interval = 20.00;
            if (System.Configuration.ConfigurationManager.AppSettings.AllKeys.Contains("DueTime"))
            {
                string IntervalValue = System.Configuration.ConfigurationManager.AppSettings["DueTime"];
                Interval = double.Parse(IntervalValue);
            }
            Interval = Interval * 1000;
            TriggerTimer = new System.Timers.Timer();
            TriggerTimer.Interval = Interval;
            TriggerTimer.Elapsed += new System.Timers.ElapsedEventHandler(TriggerTimer_Elapsed);
            if (System.IO.Directory.Exists(logPtah))
            {
                System.IO.Directory.CreateDirectory(logPtah);
            }
            GC.KeepAlive(TriggerTimer);
            GC.KeepAlive(RegisteredProcesses);
        }

        public static void StartTriggerTimer()
        {
            TriggerTimer.Start();
        }

        public static void StopTriggerTimer()
        {
            TriggerTimer.Stop();
        }

        static void TriggerTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            ExcuteProcess(null);
        }

         
        private static void ExcuteProcess(object state)
        {
            try
            {
                if (Interlocked.Exchange(ref IsExcutingProcess, 1) == 0)
                {
                    switch (_excuteMode)
                    {
                        case ExcuteMode.Parallel:
                            RegisteredProcesses.ForEach(p =>
                            {
                                new Thread(new ThreadStart(p.TrrigerProcess)).Start();
                            });
                            break;
                        case ExcuteMode.Serial:
                             RegisteredProcesses.ForEach(p =>
                            {
                                p.TrrigerProcess();
                            });
                             break;
                    }
                    Interlocked.Exchange(ref IsExcutingProcess, 0);
                }
                else
                {
                    FileUtility.Log.Log.getInstance().WriteToLog("FileMonitor Not to check new files ", logPtah);
                }
            }
            catch (Exception ex)
            {
                FileUtility.Log.Log.getInstance().WriteToLog(ex.Message, logPtah);
            }
            finally
            {
                Interlocked.Exchange(ref IsExcutingProcess, 0);
            }
            
        }
    }
}
